const Service = require('egg').Service
const sharp = require('sharp')
let Duplex = require('stream').Duplex
const QRCode = require('qrcode')
const TextToSVG = require('text-to-svg')
const textToSVG = TextToSVG.loadSync('./app/public/font/PingFang Medium.ttf');

function bufferToStream(buffer) {
  let stream = new Duplex();
  stream.push(buffer);
  stream.push(null);
  return stream;
}

function dataUrlToBuffer(string) {
  const regex = /^data:.+\/(.+);base64,(.*)$/;
  const matches = string.match(regex);
  const data = matches[2];
  return new Buffer(data, 'base64');
}

class FileUploadService extends Service {
  async creatFile(data) {
    return new Promise(async (resolve, reject) => {
      this.ctx.model.File({
        ...data
      }).save((err, data) => {
        if (err) {
          console.log(err);
          reject(err);
          return
        }
        resolve(data)
      })
    })
  }

  /**
   * 文件列表
   *
   * @param {*} [params={}]
   * @returns
   * @memberof FileUploadService
   */
  async findFiles(params = {}) {
    const pageSize = params && parseInt(params.pageSize) || 20; // 使用分页
    const page = params && parseInt(params.page) || 1;
    delete params.pageSize;
    delete params.page;
    params.creator = this.ctx.state.user.id
    return new Promise(async (resolve, reject) => {
      this.ctx.model.File.find(params)
        .limit(pageSize)
        .skip(pageSize * (page - 1))
        .sort('-createDate')
        .lean()
        .exec((err, docs) => {
          if (err) {
            reject(err);
          } else {
            resolve(docs);
          }
        });
    })
  }

  async findOneFile(id) {
    return new Promise(async (resolve, reject) => {
      this.ctx.model.File.findOne({
        _id: id
      }).lean()
        .exec((err, doc) => {
          if (err) {
            console.log(err);
            reject(err);
          } else {
            resolve(doc);
          }
        });
    })
  }

  async deleteFile(id) {
    return new Promise(async (resolve, reject) => {
      this.ctx.model.File.remove({
        _id: id
      }).lean()
        .exec((err, doc) => {
          if (err) {
            console.log(err);
            reject(err);
          } else {
            resolve(doc);
          }
        });
    })
  }

  async downloadQrCodeImage(data, accessToken) {
    const { ctx } = this;
    return new Promise(async (resolve, reject) => {
      try {
        let miniQRCode;
        if (!data.target || !data.target.shareType) { // 小程序码
          miniQRCode = await ctx.curl(`https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${accessToken}`, {
            timeout: 5000,
            method: 'POST',
            data: JSON.stringify({
              scene: data.id,
              page: data.page || 'pages/index/index',
              width: 280,
              is_hyaline: true, // 去除小程序码的白色背景
            })
          });
          if (miniQRCode.data.errcode === 45009) {
            reject(new Error('调用分钟频率受限(目前5000次/分钟，会调整)，如需大量小程序码，建议预生成。'))
            return
          }
          if (miniQRCode.data.errcode === 41030) {
            reject(new Error('所传page页面不存在，或者小程序没有发布'))
            return
          }
          console.log(miniQRCode.data)
          miniQRCode = await sharp(miniQRCode.data).resize({
            width: 180,
            height: 180,
          })
            .toBuffer();
        } else {
          const stream = await QRCode.toDataURL(data.target.url || data.imgUrl || 'text',
            {
              margin: 0,
              width: 180,
              color: {
                light: '#ffffff00'
              }
            })
          miniQRCode = dataUrlToBuffer(stream)
        }
        const result = await ctx.curl(`${data.imgUrl}?imageView2/1/w/710/h/1078`, {
          timeout: 3000,
        });

        // 分享文字
        const attributes = { fill: '#696969', stroke: '' };
        const options = { x: 0, y: 0, fontSize: 22, anchor: 'top', attributes: attributes };
        const svg = textToSVG.getSVG('长按扫描二维码查看', options);


        const Exeattributes = { fill: '#87939d', stroke: '' };
        const exeoptions = { x: 0, y: 0, fontSize: 14, anchor: 'top', attributes: Exeattributes };
        const Exesvg = textToSVG.getSVG('职行力提供技术支持', exeoptions);

        const titleAttributes = { fill: '#323232', stroke: '' };
        const titleOptions = { x: 0, y: 0, fontSize: 28, anchor: 'top', attributes: titleAttributes };
        const titleSvg = textToSVG.getSVG(data.description.slice(0, 16), titleOptions);

        const resultImg = await sharp({
          create: {
            width: 750,
            height: 1118,
            channels: 4,
            background: { r: 255, g: 255, b: 255, alpha: 1 }
          }
        })
          .jpeg()
          // .overlayWith(miniQRCode)
          // .resize(320, 240)

          .composite([{
            input: result.data,
            top: 20,
            left: 20
          },
          {
            input: {
              create: {
                width: 750,
                height: 220,
                channels: 4, // 四个通道代表多一个alpha通道，即是透明度通道
                background: { r: 255, g: 255, b: 255, alpha: .8 }
              }
            },
            gravity: sharp.gravity.south
          },

          {
            input: miniQRCode,
            top: 920,
            left: 40
          },
          {
            input: Buffer.from(titleSvg),
            top: 980,
            left: 240
          },
          {
            input: Buffer.from(svg),
            top: 1040,
            left: 240
          },
          {
            input: Buffer.from(Exesvg),
            top: 1070,
            left: 242
          }
          ])

          .toBuffer({ resolveWithObject: true })
        const uploadResult = await ctx.app.fullQiniu.uploadStream('block_editor/upload/images/' + 's_' + new Date().getTime(), bufferToStream(resultImg.data));
        if (uploadResult.ok) {
          resolve({
            url: uploadResult.url
          });
        }
      } catch (err) {
        throw err;
      };

    })
  }
}

module.exports = FileUploadService;
